package be.sc.classicnetwork.controller;

import java.io.BufferedOutputStream;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import be.sc.classicnetwork.dao.PaginationSearchResult;
import be.sc.classicnetwork.exception.ApplicationException;
import be.sc.classicnetwork.model.Image;
import be.sc.classicnetwork.model.Make;
import be.sc.classicnetwork.model.User;
import be.sc.classicnetwork.service.ServiceLocator;
import be.sc.classicnetwork.util.PropertiesUtils;

/**
 * Multi Action Controller.
 */
public class ApplicationMultiActionController extends MultiActionController {

	private final static String PAGER_OFFSET = "pager.offset";

	private final static int MAX_PAGE_ITEMS = Integer
			.parseInt(PropertiesUtils.MAX_PAGE_ITEMS);

	private ServiceLocator serviceLocator;

	/**
	 * getOffset.
	 */
	private int getOffset(HttpServletRequest request) {
		String offset = request.getParameter(PAGER_OFFSET);
		return (StringUtils.isEmpty(offset)) ? 0 : Integer.parseInt(offset);
	}

	/**
	 * initPager.
	 */
	private void initPager(HttpServletRequest request) {
		request.setAttribute("pageUrl", request.getRequestURI());
		request.setAttribute("maxPageItems", MAX_PAGE_ITEMS);
	}

	/**
	 * index.
	 */
	public ModelAndView index(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		return listAllCars(request, response);
	}

	/**
	 * home.
	 */
	public ModelAndView home(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		return new ModelAndView();
	}

	/**
	 * getListCarsModelAndView.
	 */
	@SuppressWarnings("unchecked")
	private ModelAndView getListCarsModelAndView(PaginationSearchResult result) {
		ModelAndView modelAndView = new ModelAndView("listCars");
		modelAndView.addObject("carList", result.getList());
		modelAndView.addObject("count", result.getCount());

		return modelAndView;
	}

	/**
	 * listCarsByMake.
	 */
	public ModelAndView listCarsByMake(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		initPager(request);
		String id = ServletRequestUtils.getRequiredStringParameter(request,
				"id");

		boolean enableFilterPublished = !User.getCurrentUser().isAdmin();
		int offset = getOffset(request);
		PaginationSearchResult result = getServiceLocator().getCarService()
				.findByMake(offset, MAX_PAGE_ITEMS, enableFilterPublished,
						new Make(id));

		return getListCarsModelAndView(result);
	}

	/**
	 * listCarsByModel.
	 */
	public ModelAndView listCarsByModel(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		initPager(request);
		String queryString = ServletRequestUtils.getRequiredStringParameter(
				request, "model");

		boolean enableFilterPublished = !User.getCurrentUser().isAdmin();
		int offset = getOffset(request);
		PaginationSearchResult result = getServiceLocator().getCarService()
				.findByModelOrMakeLike(offset, MAX_PAGE_ITEMS,
						enableFilterPublished, queryString);

		return getListCarsModelAndView(result);
	}

	/**
	 * listAllCars.
	 */
	public ModelAndView listAllCars(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		initPager(request);
		boolean enableFilterPublished = !User.getCurrentUser().isAdmin();
		int offset = getOffset(request);
		PaginationSearchResult result = getServiceLocator().getCarService()
				.findAll(offset, MAX_PAGE_ITEMS, enableFilterPublished);

		return getListCarsModelAndView(result);
	}

	/**
	 * viewImage.
	 */
	public void viewImage(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String id = ServletRequestUtils.getRequiredStringParameter(request,
				"id");
		String type = ServletRequestUtils.getStringParameter(request, "type");

		Image image = getServiceLocator().getCarService().findImageById(id);

		if (image == null) {
			return;
		}

		response.setContentType("image/jpeg");

		// use BufferedOutputStream for performance
		BufferedOutputStream out = new BufferedOutputStream(response
				.getOutputStream());
		try {
			// show normal image
			if (!StringUtils.isEmpty(type)) {
				response.setContentLength(image.getFile().length);
				out.write(image.getFile());
			}

			// show thumb
			else {
				response.setContentLength(image.getThumb().length);
				out.write(image.getThumb());
			}
		} finally {
			out.close();
		}
	}

	/**
	 * This method has been created to simulate an ApplicationException.
	 */
	public ModelAndView throwException(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		throw new ApplicationException("This is an Exception");
	}

	/**
	 * login.
	 */
	public ModelAndView login(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		return new ModelAndView("loginForm");
	}

	/**
	 * logout.
	 */
	public ModelAndView logout(HttpServletRequest request,
			HttpServletResponse response) {
		// invalidate the user session
		request.getSession().invalidate();

		// terminate the acegi cookie
		Cookie terminate = new Cookie(
				TokenBasedRememberMeServices.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY,
				null);
		terminate.setMaxAge(0);
		response.addCookie(terminate);
		return new ModelAndView("redirect:/index.html");
	}

	/**
	 * viewCar.
	 */
	public ModelAndView viewCar(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String id = ServletRequestUtils.getRequiredStringParameter(request,
				"id");
		return new ModelAndView().addObject(getServiceLocator().getCarService()
				.findByIdFull(id));
	}

	/**
	 * viewCarImages.
	 */
	public ModelAndView viewCarImages(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String id = ServletRequestUtils.getRequiredStringParameter(request,
				"id");
		return new ModelAndView().addObject("images", getServiceLocator()
				.getCarService().findByIdFull(id).getImages());
	}

	/**
	 * buy.
	 */
	public ModelAndView buy(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		return new ModelAndView();
	}

	/**
	 * sell.
	 */
	public ModelAndView sell(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		return new ModelAndView();
	}

	public ServiceLocator getServiceLocator() {
		return serviceLocator;
	}

	public void setServiceLocator(ServiceLocator serviceLocator) {
		this.serviceLocator = serviceLocator;
	}

}
